<?php
/**********************************************************************************
WIKINDX: Bibliographic Management system.
Copyright (C)

This program is free software; you can redistribute it and/or modify it under the terms 
of the GNU General Public License as published by the Free Software Foundation; either 
version 2 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
See the GNU General Public License for more details.

You should have received a copy of the GNU General Public License along with this program; 
if not, write to the 
Free Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA

The WIKINDX Team 2007
sirfragalot@users.sourceforge.net
**********************************************************************************/
/*****
*	NOTIFY class.
*
*	Email notification of resource changes
*****/
class NOTIFY
{
// Constructor
	function NOTIFY($db)
	{
		$this->db = $db;
		include_once("core/session/SESSION.php");
		$this->session = new SESSION();
		include_once("core/messages/MESSAGES.php");
		$this->messages = new MESSAGES();
		include_once("core/sql/STATEMENTS.php");
		$this->stmt = new STATEMENTS($this->db);
		include_once("core/styles/BIBSTYLE.php");
		$this->bibStyle = new BIBSTYLE($this->db, 'plain');
		$this->titles = array();
	}
// Send email
	function email($resourceId, $newResource = FALSE)
	{
// do nothing if admin does not allow notification
		if(!$this->session->getVar('setup_notify'))
			return;
		$wikindxTitle = $this->session->getVar("setup_title");
		if(!$wikindxTitle)
			$wikindxTitle = "WIKINDX";
		$subject = "$wikindxTitle Resource Notification";
		$headers = "From: WIKINDX\n";
		$headers .= "Reply-to: noReply\r\n";
		if(!$this->emailImmediate($resourceId, $newResource, $subject, $headers))
			return; // no notification needed
// Now deal with users with a set email threshold
		if(isset($this->users))
			$this->emailThreshold($subject, $headers);
	}
// Deal with those requiring immediate notification of a single resource change or block import
	function emailImmediate($resourceId, $newResource, $subject, $headers)
	{
		$this->earliestUserUnixTimestamp = $this->earliestNotifyUnixTimestamp = $this->greatestThreshold = FALSE;
		$userId = $this->session->getVar('setup_userId');
// Are there any users wanting notification?
		$recordset = $this->db->selectWithExceptions(array('WKX_users'), array('id', 'email', 'notify', 'notifyAddEdit', 
			'notifyThreshold', array("UNIX_TIMESTAMP(notifyTimestamp)" => 'unixNotifyTimestamp'), 
				array("UNIX_TIMESTAMP(timestamp)" => 'unixTimestamp')), 
			"WHERE id != " . $this->db->tidyInput($userId) . 
			" AND " . $this->db->formatField('notify') . "!=" . $this->db->tidyInput('N'));
		if(!$this->db->numRows($recordset)) // nothing to do
			return FALSE;
// Get this user's name (the user adding/editing a resource)
		include_once("core/user/USER.php");
		$user = new USER($this->db);
		$userAddEdit = $user->displayUserAddEditPlain($userId);
// Grab resource details
		list($title, $notifyMessage) = $this->formatTitle($resourceId, $userAddEdit);
		$message = $notifyMessage . "\n\n$title\n";
		while($row = $this->db->loopRecordset($recordset))
		{
			if($row['notifyThreshold'] > 0)
			{
				$this->users[$row['id']] = array(
											'email' => $row['email'],
											'notify' => $row['notify'],
											'notifyAddEdit' => $row['notifyAddEdit'],
											'notifyThreshold' => $row['notifyThreshold'],
											'unixNotifyTimestamp' => $row['unixNotifyTimestamp'],
											'unixTimestamp' => $row['unixTimestamp']
										);
// Store greatest user notification threshold
				if(!$this->greatestThreshold || ($row['notifyThreshold'] > $this->greatestThreshold))
					$this->greatestThreshold = $row['notifyThreshold'];
// Store earliest user notification timestamp
				if(!$this->earliestNotifyUnixTimestamp || ($row['unixNotifyTimestamp'] < $this->earliestNotifyUnixTimestamp))
					$this->earliestNotifyUnixTimestamp = $row['unixNotifyTimestamp'];
// Store earliest user notification timestamp
				if(!$this->earliestUserUnixTimestamp || ($row['unixTimestamp'] < $this->earliestUserUnixTimestamp))
					$this->earliestUserUnixTimestamp = $row['unixTimestamp'];
				continue; // deal with this in emailThreshold()
			}
// User wants notification only on new resources
			if(($row['notifyAddEdit'] == 'N') && !$newResource)
				continue;
// User wants notification only on edited resources
			if(($row['notifyAddEdit'] == 'E') && $newResource)
				continue;
			if(!$row['email']) // This should only happen if superadmin has not entered email
				continue;
			$email = $row['email'];
			include_once("core/email/EMAIL.php");
			$emailClass = new EMAIL();
			if($row['notify'] == 'A') // notify on all resources
				$emailClass->notify($email, $subject, $message, $headers);
// notify on resources in a user's bibliography (works for only a single resourceId)
			else if(($row['notify'] == 'M') && !is_array($resourceId))
			{
				$recordset2 = $this->db->select(array('WKX_user_bibliography'), array('id'), 
					" WHERE " . $this->db->formatField('userId') . '=' . 
					$this->db->tidyInput($row['id']) . 
// NB MySQL bug: http://bugs.mysql.com/bug.php?id=2047 -- append comma temporarily
					" AND FIND_IN_SET(" . $this->db->tidyInput($resourceId) . ", CONCAT(" . 
					$this->db->formatField('bibliography') . ", ','))");
				if(!$this->db->numRows($recordset2)) // This resource not in user's bibliography
					continue;
				$emailClass->notify($email, $subject, $message, $headers);
			}
		}
		return TRUE;
	}
// Email those with a notification threshold set
	function emailThreshold($subject, $headers)
	{
		$this->grabResources();
		if(empty($this->allAddedIds) && empty($this->allEditedIds))
			return; // nothing to do
		foreach($this->users as $userId => $userArray)
		{
			if(!$userArray['email']) // This should only happen if superadmin has not entered email
				continue;
			$message = $this->messages->text("user", "notifyMass4") . "\n\n\n"; // reset each time
			$thisArray = $notifyArray = array(); // reset each time
// User wants notification only on new resources
			if(!empty($this->allAddedIds) && ($userArray['notifyAddEdit'] == 'N'))
				$notifyArray = $this->grabTitlesThreshold($userArray, $this->allAddedIds);
// User wants notification only on edited resources
			else if(!empty($this->allEditedIds) && ($userArray['notifyAddEdit'] == 'E'))
				$notifyArray = $this->grabTitlesThreshold($userArray, $this->allEditedIds);
			if(empty($notifyArray) && $userArray['notify'] == 'A') // notify on all resources
// NB, if resource has not been edited, editedTimestamp is same as addedTimestamp
				$notifyArray = $this->grabTitlesThreshold($userArray, $this->allEditedIds);
// notify on resources in a user's bibliography
			else if(($userArray['notify'] == 'M'))
			{
				if(empty($notifyArray) && !empty($this->allEditedIds))
					$newArray = $this->allEditedIds;
				else if(!empty($notifyArray))
					$newArray = $notifyArray;
				else
					continue;
				$remainIds = array();
				$recordset = $this->db->select(array('WKX_user_bibliography'), array('bibliography'), 
					" WHERE " . $this->db->formatField('userId') . '=' . 
					$this->db->tidyInput($userId));
				if(!$this->db->numRows($recordset)) // User has no bibliography
					continue;
				while($row = $this->db->loopRecordset($recordset))
				{
					$bibs = explode(',', $row['bibliography']);
					foreach($newArray as $id => $field)
					{
						if(array_search($id, $bibs) !== FALSE)
							$remainIds[$id] = $field;
					}
				}
				if(empty($notifyArray)) // $field is not a formatted title but is unixTimestamp from $this->allEditedIds
					$notifyArray = $this->grabTitlesThreshold($userArray, $remainIds);
				else
					$notifyArray = $remainIds;
			}
			if(empty($notifyArray))
				continue;
// If more than 10 added resources, simply grab the number of added resources
			$size = sizeof($notifyArray);
			if($size > 10)
				$message = $this->messages->text("user", "notifyMass3", $size);
			else
				$message .= join("\n\n", $notifyArray);
			include_once("core/email/EMAIL.php");
			$emailClass = new EMAIL();
			$emailClass->notify($userArray['email'], $subject, $message, $headers);
// set this user's WKX_users.notifyTimestamp to current date
			$this->db->query("UPDATE `WKX_users` set `notifyTimestamp` = NOW() WHERE " . 
				$this->db->formatField('id') . '=' . $this->db->tidyInput($userId));
		}
	}
// grab titles from main list only if user threshold has been passed and resources have been added/edited since the user's last notification
	function grabTitlesThreshold($userArray, $idArray)
	{
// no. seconds in 1 day
		$day1secs = 86400;
		$userThreshold = $userArray['notifyThreshold'] * $day1secs;
		$now = time();
		$passed = (($now - $userArray['unixNotifyTimestamp']) > $userThreshold) ? TRUE : FALSE;
		$notifyArray = array();
		foreach($idArray as $id => $resourceTimestamp)
		{
			if(time())
			if(($resourceTimestamp > $userArray['unixNotifyTimestamp']) && ($passed))
				$notifyArray[$id] = $this->titles[$id];
		}
		return $notifyArray;
	}
// Grab resources at greatest threshold following editing or addition.
// Resources must have NOW() - timestamp  that is less than the greatest notification threshold
	function grabResources()
	{
		$greatestThreshold = 86400 * $this->greatestThreshold;
		$sql = $this->db->selectNoExecuteWithExceptions(array("WKX_resource"), 
			array_merge($this->stmt->listFields(), 
				array(array("UNIX_TIMESTAMP(timestampAdd)" => 'addUnixTimestamp')), 
				array(array("UNIX_TIMESTAMP(timestamp)" => 'editUnixTimestamp'))), 
			$this->stmt->selectJoin());
// grab greatest possible number of added resources
		$condition = ' WHERE ' . 
			'UNIX_TIMESTAMP(' . $this->db->formatField('timestampAdd') . ')>' . 
			$this->db->tidyInput($this->earliestNotifyUnixTimestamp);
		$recordset = $this->db->query($sql . $condition);
		$this->allAddedIds = $this->allEditedIds = array();
		while($row = $this->db->loopRecordset($recordset))
		{
			if(!array_key_exists($row['resourceId'], $this->titles))
				$this->formatTitleThreshold($row);
			$this->allAddedIds[$row['resourceId']] = $row['addUnixTimestamp'];
		}
// grab greatest possible number of edited resources
		$condition = " WHERE " . 
			'UNIX_TIMESTAMP(' . $this->db->formatField('timestamp') . ')>' . 
			$this->db->tidyInput($this->earliestNotifyUnixTimestamp);
		$recordset = $this->db->query($sql . $condition);
		while($row = $this->db->loopRecordset($recordset))
		{
			if(!array_key_exists($row['resourceId'], $this->titles))
				$this->formatTitleThreshold($row);
			$this->allEditedIds[$row['resourceId']] = $row['editUnixTimestamp'];
		}
	}
// Format the resource entry from the SQL row (threshold)
	function formatTitleThreshold($row)
	{
// Data stored in database as UTF-8
		$title = utf8_decode($this->bibStyle->process($row));
		$this->titles[$row['resourceId']] = $title;
	}
// Format the resource entry from the given resource ID.  $resourceIds is either a single ID or an array of IDs for mass imports
	function formatTitle($resourceId, $userAddEdit)
	{
		$title = '';
		if(is_array($resourceId)) // always an array coming from emailThreshold()
		{
// If more than 10 added resources, simply grab the number of added resources
			$size = sizeof($resourceId);
			if($size > 10)
			{
				$notifyMessage = $this->messages->text("user", "notifyMass1", $userAddEdit);
				$notifyMessage .= ' ' . $this->messages->text("user", "notifyMass2", $size);
				$title = FALSE;
			}
			else
			{
				foreach($resourceId as $id)
				{
					$sql = $this->db->selectNoExecute(array("WKX_resource"), 
						$this->stmt->listFields(), $this->stmt->selectJoin());
					$sql .= " WHERE WKX_resource.id=" . $this->db->tidyInput($id);
					$recordset = $this->db->query($sql);
					$row = $this->db->fetchRow($recordset);
// Data stored in database as UTF-8
					$this->titles[$row['resourceId']] = utf8_decode($this->bibStyle->process($row));
				}
				$title = join("\n\n", $this->titles);
				$notifyMessage = $this->messages->text("user", "notifyMass1", $userAddEdit);
			}
		}
		else
		{
			$sql = $this->db->selectNoExecute(array("WKX_resource"), $this->stmt->listFields(), 
				$this->stmt->selectJoin());
			$sql .= " WHERE WKX_resource.id=" . $this->db->tidyInput($resourceId);
			$recordset = $this->db->query($sql);
			$row = $this->db->fetchRow($recordset);
// Data stored in database as UTF-8
			$title = utf8_decode($this->bibStyle->process($row));
			$notifyMessage = $this->messages->text("user", "notify", $userAddEdit);
		}
		return array($title, $notifyMessage);
	}
}
?>
